package beanstao.util.store.domainobject;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.dom4j.Element;

import beanstao.util.setting.Setting;
import beanstao.util.store.database.Field;
import beanstao.util.store.database.Fields;


/**
 * 针对每个模块的所有Domain的字段列表的Setting管理类。<BR>
 * 重点：<BR>
 * 1.面向模块，每个模块都有自己的唯一的 DomainSetting<BR>
 * 2.通过Domain的关键字(如:Domain是数据表的表时,关键字是表名; Domain是Element时,关键字是LocalName)
 * @author beanstao@google.com 
 */
public class DomainSetting extends Setting<Element>
{

	/**
	 * @return 返回本类型的单建实例(延迟加载,并对多线程进行处理)
	 */
	public static DomainSetting ME()
	{
		return Single.instance;
	}

	/**
	 * 为单建模式设计的内部静态类型
	 */
	static class Single
	{
		/**
		 * 多线程锁
		 */
		static Object lock = new Object();
		static
		{
			synchronized (lock)
			{
				instance = new DomainSetting();
			}
		}
		static DomainSetting instance;
	}

	/**
	 * 针对单建模式,私有化本类型构造函数
	 */
	private DomainSetting()
	{
	}

	protected final HashMap<String, Fields> _DomainFileds = new HashMap<String, Fields>();

	public Fields getFields(final String key)
	{
		return _DomainFileds.get(key.toLowerCase());
	}

	public Set<String> getFieldNames()
	{
		return _DomainFileds.keySet();
	}

	public Collection<Fields> getFieldsList()
	{
		return _DomainFileds.values();
	}

	@Override
	protected void fillSettingData(final Element element)
	{
		try
		{
			ArrayList<Field> publicFieldColumns = this.getFields(element, "//publicfields");
			List<?> domainElementList = element.selectNodes("//domainObject[@class]");
			for (Object object : domainElementList)
			{
				if (!(object instanceof Element))
					continue;
				Element domainElement = (Element) object;
				ArrayList<Field> fieldColumns = this.getFields(domainElement, "fields");
				fieldColumns.addAll(publicFieldColumns);

				Fields fields = new Fields(domainElement.attributeValue("name").toLowerCase(), fieldColumns);
				fields.setClassName(domainElement.attributeValue("class"));
				_DomainFileds.put(fields.getName().toLowerCase(), fields);
				this.logDebug(String.format("字段列表 %s 解析成功。", fields.getName().toLowerCase()));
			}
		}
		catch (Exception e)
		{
			this.logWarn("填充本类型的具体数据时发生异常。", e);
		}
	}

	private ArrayList<Field> getFields(final Element element, final String xpath)
	{
		ArrayList<Field> columns = new ArrayList<Field>();
		Element tmpEle = (Element) element.selectSingleNode(xpath);
		List<Element> fieldList = tmpEle.elements();

		for (Element field : fieldList)
		{
			Field column = null;
			if (field.getName().equals("field"))
				try
				{
					column = Field.fromGeneralElement(field);
					if (column != null)
						columns.add(column);
				}
				catch (Exception e)
				{
					this.logWarn("DataField解析出错:" + field.asXML(), e);
				}
		}
		return columns;
	}

}
